package cn.skyquant.quant4j.service.boot.model.account;

import cn.skyquant.quant4j.api.account.AccountDTO;
import cn.skyquant.quant4j.api.account.AccountService;
import cn.skyquant.quant4j.api.authority.UserDTO;
import cn.skyquant.quant4j.api.dto.ResultDTO;
import cn.skyquant.quant4j.api.enums.BorkerType;
import cn.skyquant.quant4j.api.sms.SmsService;
import cn.skyquant.quant4j.sdk.enums.Status;
import cn.skyquant.quant4j.sdk.util.bean.BeanTools;
import cn.skyquant.quant4j.service.boot.model.authority.AppContext;
import cn.skyquant.quant4j.service.boot.model.authority.User;
import cn.skyquant.quant4j.service.boot.model.authority.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.Optional;


@Service("AccountServiceImpl")
public class AccountServiceImpl implements AccountService {
    @Autowired
    SmsService smsService;
    @Autowired
    AccountRepository accountRepository;
    @Autowired
    AccountHisRepository accountHisRepository;
    @Autowired
    UserRepository userRepository;
    @Autowired
    AppContext appContext;

    static final ResultDTO success = ResultDTO.success();
    static final ResultDTO error = ResultDTO.error("账户不存在");
    static final ResultDTO error1 = ResultDTO.error("未登陆用户");
    static final ResultDTO error2 = ResultDTO.error("手机号对应用户不存在");

    @Transactional
    @Override
    public ResultDTO<AccountDTO> reg(String accountCode, BorkerType borkerType, String accountName, String borkerName, String currency, String accountType, String parentCode) {
        if (appContext.get() == null) {
            return error1;
        }
        UserDTO userDTO = appContext.get();
        String tel = userDTO.tel;
        Optional<User> userOptional = userRepository.findByTel(tel);
        if (!userOptional.isPresent()) {
            return error2;
        }
        Optional<Account> accountExist = accountRepository.findByCodeAndBorkerType(accountCode,borkerType);
        if (!accountExist.isPresent()) {
            Account newAccount = new Account();
            newAccount.code = accountCode;
            newAccount.borkerType = borkerType;
            newAccount.type = accountType;
            newAccount.name = accountName;
            newAccount.currency = currency;
            newAccount.borkerName = borkerName;
            newAccount.parentCode = parentCode;
            newAccount.equity = 0;
            newAccount.balance = 0;
            newAccount.usedMargin = 0;
            newAccount.user = userOptional.get();
            newAccount.notice = Status.S;//默认不短信通知
            Account entity = accountRepository.save(newAccount);
            return ResultDTO.success(convertAccountToAccountDTO(entity));
        } else {
            AccountDTO accountDTOExist = convertAccountToAccountDTO(accountExist.get());
            return ResultDTO.success(accountDTOExist);
        }
    }

    @Transactional
    @Override
    public ResultDTO<Void> update(String code,BorkerType borkerType, double balance, double equity, double usedMargin, long borkerTime) {
        Optional<Account> accountOptional = accountRepository.findByCodeAndBorkerType(code,borkerType);
        if (accountOptional.isPresent()) {
            Account account = accountOptional.get();
            account.balance = balance;
            account.equity = equity;
            account.usedMargin = usedMargin;
            AccountHis accountHis = new AccountHis();
            accountHis.account = account;
            accountHis.balance = balance;
            accountHis.equity = equity;
            accountHis.usedMargin = usedMargin;
            accountHis.borkerTime = new Date(borkerTime);
            accountHisRepository.save(accountHis);
            return success;
        } else {
            return error;
        }
    }

    @Override
    public ResultDTO<Void> notice(int accountId) {
        Optional<Account> accountOptional = accountRepository.findById(accountId);
        if (accountOptional.isPresent()) {
            Account account = accountOptional.get();
            User user = account.user;
            if (user != null) {
                double cash = new BigDecimal(account.equity - account.usedMargin).setScale(2, RoundingMode.HALF_UP).doubleValue();
                return smsService.balanceNotice(user.tel, user.name, account.equity, cash);
            }
        }
        return error;
    }

    @Override
    public ResultDTO<AccountDTO> get(String accountCode, BorkerType borkerType) {
        Optional<Account> accountExist = accountRepository.findByCodeAndBorkerType(accountCode, borkerType);
        if (accountExist.isPresent()) {
            AccountDTO accountDTOExist = convertAccountToAccountDTO(accountExist.get());
            return ResultDTO.success(accountDTOExist);
        } else {
            return ResultDTO.error2;
        }
    }

    @Override
    public ResultDTO<AccountDTO> create(String accountCode, BorkerType borkerType, String accountType, String accountName, String borkerName, String currency, String parentCode) {
        Optional<Account> accountExist = accountRepository.findByCodeAndBorkerType(accountCode, borkerType);
        //如果不存在
        if (accountExist.isPresent()) {
            AccountDTO accountDTOExist = convertAccountToAccountDTO(accountExist.get());
            return ResultDTO.success(accountDTOExist);
        } else {
            Account newAccount = new Account();
            newAccount.code = accountCode;
            newAccount.borkerType = borkerType;
            newAccount.type = accountType;
            newAccount.name = accountName;
            newAccount.currency = currency;
            newAccount.borkerName = borkerName;
            newAccount.parentCode = parentCode;
            newAccount.equity = 0;
            newAccount.balance = 0;
            newAccount.usedMargin = 0;
            newAccount.status = Status.A;//默认状态开启
//            newAccount.user = null;
            newAccount.notice = Status.S;//默认不短信通知
            Account entity = accountRepository.save(newAccount);
            return ResultDTO.success(convertAccountToAccountDTO(entity));
        }
    }

    @Transactional
    @Override
    public ResultDTO<Void> updateType(int accountId, String type) {
        Optional<Account> accountExist = accountRepository.findById(accountId);
        if (accountExist.isPresent() && type!=null) {
            Account account = accountExist.get();
            account.type = type;
        }
        return ResultDTO.success;
    }


    private static final AccountDTO convertAccountToAccountDTO(Account account) {
        AccountDTO accountDTO = new AccountDTO();
        BeanTools.copyPublicFields(account, accountDTO);
        return accountDTO;
    }

}
